<script setup>
import { nextTick, ref } from "vue";
// Markmap视图渲染库
import { Markmap } from "markmap-view";
// Markmap核心转换库
import { Transformer } from "markmap-lib";
// Markmap工具栏组件
import { Toolbar } from "markmap-toolbar";
import { checkSession, getSystemInfo } from "@/store/cache";
import { httpGet, httpPost } from "@/utils/http";
import { ElMessage } from "element-plus";
import { Download } from "@element-plus/icons-vue";
import { useSharedStore } from "@/store/sharedata";

// 左侧面板高度（窗口高度-105px）
const leftBoxHeight = ref(window.innerHeight - 105)
// 右侧面板高度（整个窗口高度）
const rightBoxHeight = ref(window.innerHeight)
// 用户输入的AI提示词
const prompt = ref('')
// 转换后的Markdown文本
const text = ref('')
// 用户输入的原始内容
const content = ref(text.value)
// 生成的HTML内容
// const html = ref('')

// 是否登录
const isLogin = ref(false)
// 登录的用户信息
const loginUser = ref({power: 0})
// Markdown转换器实例
const transformer = new Transformer()
const store = useSharedStore()
const loading = ref(false)
// SVG元素引用
const svgRef = ref(null)
// Markmap实例引用
const markMap = ref(null)
// AI模型列表
const models = ref([])
// 选中的模型ID
const modelID = ref(0)

getSystemInfo().then(res => {
  // 系统默认的Markdown文本
  text.value = res.data['mark_map_text']
  // 同步到用户编辑区
  content.value = text.value
  initData()
  // 下一次DOM更新后初始化思维导图
  nextTick(() => {
    try{
      // 创建Markmap实例
      markMap.value = Markmap.create(svgRef.value)
      // 创建工具栏
      const { el } = Toolbar.create(markMap.value)
      // 将工具栏添加到DOM
      document.getElementById('toolbar').append(el)
      update()
    }catch (e) {
      console.error(e)
    }
  })
}).catch(e => {
  ElMessage.error('获取系统配置失败：'+e.message)
})

const initData = () => {
  httpGet('api/model/list').then(res => {
    for (let v of res.data) {
      models.value.push(v)
    }
    modelID.value = models.value[0].id
  }).catch(e => {
    ElMessage.error('获取模型数据失败：'+e.message)
  })

  checkSession().then(user => {
    loginUser.value = user
    isLogin.value = true
  }).catch(() => {})

}

// 更新思维导图函数
const update = async () => {
  try {
    // 处理并转换内容，设置Markmap数据
    const {root} = transformer.transform(processContent(text.value))
    // 设置新数据
    await markMap.value.setData(root)
    // 自适应视图
    markMap.value.fit()
  }catch (e) {
    console.error(e)
  }
}

// Markdown内容处理函数
const processContent = (text) => {
  if (!text) {
    return text
  }
  const arr = []
  const lines = text.split("\n")
  for (let line of lines) {
    // 清理特殊符号和序号
    if (line.indexOf("```") !== -1) {
      continue;
    }
    // 移除Markdown特殊符号
    line = line.replace(/([*_~`>])|(\d+\.)\s/g, "");
    arr.push(line);
  }
  return arr.join("\n");
}

// 窗口大小变化时调整UI
window.onresize = () => {
  leftBoxHeight.value = window.innerHeight - 145
  rightBoxHeight.value = window.innerHeight - 85
}

// 手动生成思维导图函数
const generate = () => {
  // 使用用户输入的原始内容
  text.value = content.value
  // 更新视图
  update()
}

// 使用 AI 智能生成
const generateAI = () => {
  text.value = ''
  if (prompt.value === '') {
    return ElMessage.error('请输入你的需求')
  }
  if (!isLogin.value) {
    store.setShowLoginDialog(true)
    return
  }
  loading.value = true
  httpPost('api/markMap/gen',{prompt: prompt.value,model_id: modelID.value}).then(res => {
    text.value = res.data
    // 处理内容
    content.value = processContent(text.value)
    const model = getModelById(modelID.value)
    // 扣除用户算力
    loginUser.value.power -= model.power
    // DOM更新后刷新视图
    nextTick(() => {update()})
    loading.value = false
  }).catch(e => {
    ElMessage.error('生成思维导图失败：'+e.message)
    loading.value = false
  })
}

// 根据ID查找模型
const getModelById = (modelId) => {
  for (let m of models.value) {
    if (m.id === modelId) {
      return m
    }
  }
}

// 下载思维导图为图片
const downloadImage = () => {
  // 1. 获取思维导图容器元素
  const svgElement = document.getElementById('markmap')
  // 2. 创建 XML 序列化器，用于将 SVG 元素转换为字符串
  const serializer = new XMLSerializer()
  // 3. 添加 XML 声明头并将 SVG 序列化为字符串
  const source = '<?xml version="1.0" standalone="no"?>\r\n' + serializer.serializeToString(svgRef.value);
  // 4. 创建图片对象用于加载 SVG
  const image = new Image()
  // 5. 将 SVG 字符串编码为 Data URL 格式（SVG+xml）
  image.src = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(source)
  // 6. 创建 canvas 元素用于最终渲染
  const canvas = document.createElement('canvas')
  // 7. 设置 canvas 尺寸与 SVG 容器相同
  canvas.width = svgElement.offsetWidth
  canvas.height = svgElement.offsetHeight
  // 8. 获取 canvas 2D 绘图上下文
  let context = canvas.getContext('2d')
  // 9. 清除 canvas 区域（确保背景透明）
  context.clearRect(0,0,canvas.width,canvas.height)
  // 10. 设置填充颜色为白色（创建白色背景）
  context.fillStyle = 'white'
  // 11. 用白色填充整个 canvas 区域（避免透明背景）
  context.fillRect(0,0,canvas.width,canvas.height)
  // 12. 当 SVG 图片加载完成后执行
  image.onload = function () {
    // 13. 将 SVG 绘制到 canvas 上（左上角开始绘制）
    context.drawImage(image,0,0)
    // 14. 创建下载链接元素
    const a = document.createElement('a')
    // 15. 设置下载文件名为固定值
    a.download = 'geek-ai-xmind.png'
    // 16. 将 canvas 内容转换为 PNG 格式的 Data URL
    a.href = canvas.toDataURL(`image/png`);
    // 17. 模拟点击下载链接（触发浏览器下载）
    a.click();
  }
}

</script>

<template>
  <div>
    <div class="page-mark-map">
      <div class="inner custom-scroll">
        <div class="mark-map-box" :style="{height: leftBoxHeight + 'px'}">
          <h2>思维导图创作中心</h2>

          <div class="mark-map-params">
            <el-form label-width="80px" label-position="left">
              <div class="param-line">你的需求？</div>

              <div class="param-line">
                <el-input v-model="prompt"
                          :autosize="{ minRows: 4, maxRows: 6 }"
                          type="textarea"
                          placeholder="请给AI输入提示词，让AI帮你完善"/>
              </div>

              <div class="param-line">请选择生成思维导图的AI模型</div>

              <div class="param-line">
                <el-select v-model="modelID" placeholder="请选择模型" style="width: 100%">
                  <el-option v-for="item in models" :key="item.id" :label="item.name" :value="item.id">
                    <span>{{item.name}}</span>
                    <el-tag style="margin-left: 5px; position: relative; top: -2px" type="info" size="small">
                      {{item.power}}算力
                    </el-tag>
                  </el-option>
                </el-select>
              </div>

              <div class="text-info">
                <el-text type="primary">
                  当前可用算力：<el-text type="warning">{{loginUser.power}}</el-text>
                </el-text>
              </div>

              <div class="submit-btn flex-center">
                <el-button style="width: 200px" type="primary" :dark="false" round @click="generateAI" :loading="loading">
                  生成思维导图
                </el-button>
              </div>

              <div class="param-line">使用已有内容生成？</div>

              <div class="param-line">
                <el-input v-model="content"
                          :autosize="{ minRows: 4, maxRows: 6 }"
                          type="textarea"
                          placeholder="请用markdown语法输入您想要生成思维导图的内容！"/>
              </div>

              <div class="param-line flex-center">
                <el-button color="rgb(78, 51, 254)" style="width: 200px"
                :dark="false" round @click="generate">
                  直接生成（免费）
                </el-button>
              </div>

            </el-form>
          </div>
        </div>

        <div class="chat-box">
          <div class="body" id="markmap">
            <svg ref="svgRef" :style="{ height: rightBoxHeight + 'px' }"/>
            <div id="toolbar">
              <el-button @click="downloadImage" type="primary">
                <el-icon>
                  <Download/>
                </el-icon>
                <span>下载图片</span>
              </el-button>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<style lang="stylus">
@import "../assets/css/mark-map.styl"
@import "../assets/css/custom-scroll.styl"
</style>